
#ifndef __MY_SOCKET__
#define __MY_SOCKET__ 

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <iostream>

namespace wzh
{
  class Sock 
  {
  public:
    Sock() : _sock(-1) 
    {}
    ~Sock()
    {
      close(_sock);
    }

    void Socket()
    {
      _sock = socket(AF_INET, SOCK_STREAM, 0);
      if (_sock == -1)
      {
          throw std::runtime_error("Failed to create socket");
      }
    }

    void Bind(int port)
    {
      if (_sock == -1)
      {
          throw std::runtime_error("Socket is not initialized");
      }
      sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_addr.s_addr = INADDR_ANY;
      addr.sin_port = htons(port);
      
      socklen_t len = sizeof(addr);

      if (bind(_sock, (sockaddr *)&addr, sizeof(addr)) == -1)
      {
          throw std::runtime_error("Failed to bind socket");
      }
    }

    void Listen(int sz)
    {
        if (_sock == -1)
        {
            throw std::runtime_error("Socket is not initialized");
        }
        if (listen(_sock, sz) == -1)
        {
            throw std::runtime_error("Failed to listen on socket");
        }
    }

    void Connect(const std::string &ip, const int port)
    {
        if (_sock == -1)
        {
            throw std::runtime_error("Socket is not initialized");
        }
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip.c_str());
        addr.sin_port = htons(port);

        if (connect(_sock, (sockaddr *)&addr, sizeof(addr)) == -1)
        {
            throw std::runtime_error("Failed to connect to server");
        }
    }

    size_t Accept()
    {
        if (_sock == -1)
        {
            throw std::runtime_error("Socket is not initialized");
        }
        sockaddr_in addr;
        socklen_t len = sizeof(addr);
        size_t client_fd = accept(_sock, (sockaddr *)&addr, &len);
        if (client_fd == -1)
        {
            throw std::runtime_error("Failed to accept connection");
        }
        return client_fd;
    }

     void Close()
      {
          if (_sock != -1)
          {
              close(_sock);
              _sock = -1;
          }
      }

    size_t FD()
    {
      return _sock;
    }
  private:
    size_t _sock;
  };
}


#endif 
